package com.jeomo.common.log.interceptor;

import cn.hutool.json.JSONObject;
import com.jeomo.common.log.annotation.LogRecord;
import com.jeomo.common.log.entity.SysLog;
import com.jeomo.common.log.service.ILogService;
import com.jeomo.shiro.dto.LoginInfo;
import com.jeomo.shiro.util.LoginSessionUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.Map;

@Aspect
@Component
public class LogInterceptor {

    @Autowired
    private ILogService logRecorder;

    /**
     * 设置操作日志切入点
     */
    @Pointcut("@annotation(com.jeomo.common.log.annotation.LogRecord)")
    public void logPointCut() {
    }

    /**
     * 设置异常日志切入点
     */
    @Pointcut("execution(* com.jeomo.*.controller.*.*(..))")
    public void exceptionLogPointCut() {

    }

    @Around(value = "logPointCut()")
    public Object saveOperLog(ProceedingJoinPoint point) throws Throwable {
        long beginTime = System.currentTimeMillis();
        Object result = point.proceed();
        long time = System.currentTimeMillis() - beginTime;
        try {
            printlog(point, time);
        } catch (Exception e) {
        }
        return result;
    }

    /**
     * @param point    切入点
     * @param costTime 请求耗时
     */
    private void printlog(ProceedingJoinPoint point, long costTime) {
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();
        LogRecord logRecord = method.getAnnotation(LogRecord.class);
        String className = point.getTarget().getClass().getName();
        String methodName = method.getName();
        //Object[] args = point.getArgs();

        LocalDateTime now = LocalDateTime.now();
        String module = logRecord.module();
        String type = logRecord.type();
        String memo = logRecord.memo();
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String remoteAddr = request.getRemoteAddr();
        String requestURL = request.getRequestURI();
        Map<String, String[]> parameterMap = request.getParameterMap();
        int contentLength = request.getContentLength();

        JSONObject requestParams = new JSONObject(parameterMap);
        SysLog sysLog = new SysLog();
        LoginInfo currentLoginInfo = LoginSessionUtil.getCurrentLoginInfo();
        sysLog.setLoginUser(currentLoginInfo.getUsername());
        sysLog.setOrgCode(currentLoginInfo.getOrgCode());
        sysLog.setModule(module);
        sysLog.setBusinessType(type);
        sysLog.setLoginIp(remoteAddr);
        sysLog.setRequestPath(requestURL);
        sysLog.setHandleTime(new Date());
        sysLog.setRequestParam(requestParams.toString());
        sysLog.setTimeCost(costTime);
        sysLog.setMemo(memo);
        logRecorder.recordLog(sysLog);
    }

    private String readStrFromRequest(HttpServletRequest request) {
        BufferedReader br = null;
        String str, wholeStr = "";
        try {
            br = request.getReader();
            while((str = br.readLine()) != null){
                wholeStr += str;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return wholeStr;
    }
}
